#pragma once

#include "engine_impl.hh"
#include "../corelib/singleton.hpp"
#include <unordered_map>
#include <cstdint>

namespace kratos { namespace engine {

// Path pool
class PathPool {
    // Path info.
    struct PathInfo {
        // ctor
        PathInfo() {
            roundIndex = 0;
        }
        PathList pathList; // path list
        std::size_t roundIndex; // roundrobin
    };
    using SitePathMap = UNORDERED_MAP(SiteType, PathInfo, PathPool_sitePathMap_);
    using SiteIDPathMap = UNORDERED_MAP(std::uint64_t, PathID, PathPool_siteIDPathMap_);
    SitePathMap sitePathMap_; // {site type, path info}
    SiteIDPathMap siteIDPathMap_; //  {site ID, path ID}s
    std::int32_t maxCnt_; // maximum count for path
    EngineImpl* engine_; // Engine

public:
    // ctor
    // @param engine Engine
    PathPool(EngineImpl* engine);
    // dtor
    ~PathPool();
    // Start
    // @param config configuration
    // @retval true
    // @retval false fail
    bool start(kconfig::Config* config);
    // Add a new path
    // @param siteType grid type
    // @param pathID path ID
    // @retval true
    // @retval false fail
    bool addPath(SiteType siteType, PathID pathID);
    // Remove a path
    // @param siteType grid type
    // @param pathID path ID
    // @retval true
    // @retval false fail
    void removePath(SiteType siteType, PathID pathID);
    // Returns a path
    // @param siteType grid type
    // @param userData reserved
    // @retval INVALID_PATH_ID try to find a new path
    // @retval path ID
    PathID getPath(SiteType siteType, UserData userData);
    // Returns a path
    // @param siteID site ID
    // @param userData reserved
    // @retval INVALID_PATH_ID try to find a new path
    // @retval path ID
    PathID getPath(const grid::SiteID& siteID, UserData userData);

private:
    // Returns a path
    // @param pathInfo PathInfo
    // @retval path ID
    // @retval INVALID_PATH_ID path not found
    PathID selectPath(PathInfo& pathInfo);
};

}}
